home *** CD-ROM | disk | FTP | other *** search
/ Celestin Apprentice 4 / Apprentice-Release4.iso / Source Code / Libraries / VideoToolbox 95.11.08 / VideoToolboxSources / SetOnePixel.c < prev    next >
Encoding:
Text File  |  1995-07-27  |  10.2 KB  |  279 lines  |  [TEXT/CWIE]

  1.  memory", i.e. they don't give the
  2. Memory Manager any pretext for shuffling around the memory allocations, and
  3. change its master pointers. That's why it's OK to dereference the pixmap handle,
  4. i.e. use a local copy of the pixmap's master pointer.
  5.  
  6. All the routines in this file call either SetPixmapPixel or GetPixmapPixel. Both
  7. run fast by caching the information that they get about your Bit/Pixmap from
  8. RectToAddress. SetPixmapPixel and GetPixmapPixel each have their own cache.
  9.  
  10. HISTORY:
  11. 4/4/89    dgp wrote it as SetIPixel.c
  12. 9/8/90    dgp updated to work with 32 bit QuickDraw, if present.
  13. 10/15/90 bf renamed SetIPixelGW.c and modified for drawing to off screen pix maps.
  14. 4/26/92    dgp    Merged the two variants: SetIPixel.c and SetIPixelGW.c to produce the
  15.             new file SetOnePixel.c. 
  16.             Renamed SetIPixelGW to SetPixmapPixel.
  17.             Renamed GetIPixelGW to GetPixmapPixel.
  18.             Renamed SetIPixel to SetDevicePixel.
  19.             Renamed GetIPixel to GetDevicePixel.
  20.             Added SetOnePixel and GetOnePixel.
  21.             Generalized to handle any pixelSize, and accept bitmaps as well
  22.             as pixmaps.
  23. 12/23/92 dgp Doubled the speed of SetPixmapPixel and GetPixmapPixel (and thus sped up
  24.             all the routines that call them) by caching the answers from RectToAddress. 
  25.             The cache doubles the speed, but see CAUTION above.Introduced compile-time 
  26.             flag to optionally disable this new cache.
  27. 1/6/93 dgp    Fixed tiny but disastrous bug in GetPixmapPixel (wasn't saving old x and y).
  28. 1/22/93    dgp    Check more PixMap fields to make sure cache is not stale. Deleted the
  29.             warning about stale caches from the documentation.
  30. 2/7/93    dgp Wrote SetPixelsQuickly.c.
  31. 7/9/93    dgp check for 32-bit addressing capability.
  32. 6/18/94    dgp    can32 is now computed by calling TrapAvailable(_SwapMMUMode), which 
  33.             returns the correct answer even on Macs with dirty ROMs.
  34. 5/23/95 dgp Apple changed the prototype in the header file from SwapMMUMode(char *) to 
  35.             SwapMMUMode(signed char *). To retain compatibility with both old and new
  36.             headers, I cast the argument (void *).
  37. */
  38. #include "VideoToolbox.h"
  39. #ifndef __TRAPS__
  40.     #include <Traps.h>        // _SwapMMUMode
  41. #endif
  42. #define USE_CACHE 1    // true or false
  43.  
  44. void SetOnePixel(int x,int y,unsigned long value)
  45. // Assumes (x,y) is in the local coordinate system of the current port.
  46. {
  47.     WindowPtr window;
  48.     PixMapPtr pm;
  49.     
  50.     GetPort(&window);
  51.     if(x<window->portRect.left || x>=window->portRect.right
  52.         || y<window->portRect.top || y>=window->portRect.bottom)return;
  53.     // Is it a CGrafPort or a GrafPort?
  54.     if(((CGrafPtr)window)->portVersion<0)        // It's a CGrafPort,
  55.         pm = *((CGrafPtr)window)->portPixMap;    // pass pixmap ptr.
  56.     else                                         // It's a GrafPort,
  57.         pm = (PixMapPtr) &window->portBits;        // pass bitmap ptr.
  58.     SetPixmapPixel(pm,x,y,value);
  59. }
  60.  
  61. unsigned long GetOnePixel(int x,int y)
  62. // Assumes (x,y) is in the local coordinate system of the current port.
  63. {
  64.     WindowPtr window;
  65.     PixMapPtr pm;
  66.     
  67.     GetPort(&window);
  68.     if(x<window->portRect.left || x>=window->portRect.right
  69.         || y<window->portRect.top || y>=window->portRect.bottom)return 0;
  70.     // Is it a CGrafPort or a GrafPort?
  71.     if(((CGrafPtr)window)->portVersion<0)        // It's a CGrafPort,
  72.         pm = *((CGrafPtr)window)->portPixMap;    // pass pixmap ptr.
  73.     else                                         // It's a GrafPort,
  74.         pm = (PixMapPtr) &window->portBits;        // pass bitmap ptr.
  75.     return GetPixmapPixel(pm,x,y);
  76. }
  77.  
  78. void SetPixmapPixel(register PixMapPtr pmPtr,int x,int y,unsigned long value)
  79. // Pokes a value into a pixel of any size. Accepts either pixmap or bitmap.
  80. // Assumes (x,y) is in the coordinate system of the bit/pixmap.
  81. // Speed is enhanced by reusing the cached information from last time if it's the
  82. // same Pix/Bitmap as last time, i.e. same address, baseAddr,rowBytes, and bounds.
  83. // You can force it to flush its cache by passing a NULL PixMap address.
  84. {
  85.     static PixMapPtr oldPmPtr=(PixMapPtr)-1;
  86.     static int oldX,oldY;
  87.     static short rowBytes,logPixelSize,bitsOffset;
  88.     static unsigned char *pixelPtr;
  89.     static BitMap oldMap;
  90.     int shift;
  91.     unsigned char mask;
  92.     signed char mode32=true32b;
  93.     Rect r;
  94.     Boolean can32;
  95.  
  96.     can32=TrapAvailable(_SwapMMUMode);
  97.     if(!USE_CACHE || pmPtr!=oldPmPtr
  98.         || pmPtr->baseAddr!=oldMap.baseAddr 
  99.         || pmPtr->rowBytes!=oldMap.rowBytes 
  100.         || *(long *)&pmPtr->bounds.top!=*(long *)&oldMap.bounds.top
  101.         || *(long *)&pmPtr->bounds.bottom!=*(long *)&oldMap.bounds.bottom){
  102.         // Cache is stale. Get fresh values.
  103.         short pixelSize;
  104.         SetRect(&r,x,y,x+1,y+1);
  105.         pixelPtr=RectToAddress(pmPtr,&r,&rowBytes,&pixelSize,&bitsOffset);
  106.         if(pixelPtr==NULL){
  107.             oldPmPtr=(PixMapPtr)-1;    // invalidate cache
  108.             return;
  109.         }
  110.         oldPmPtr=pmPtr;
  111.         oldMap=*(BitMap *)pmPtr;
  112.         logPixelSize=Log2L(pixelSize);
  113.     }else{
  114.         // Cache is fresh. Merely correct for changes in x and y.
  115.         if(pixelPtr==NULL)return;
  116.         if(logPixelSize<3){
  117.             register long bits;
  118.             bits=bitsOffset+(long)(x-oldX)<<logPixelSize;
  119.             pixelPtr+=bits>>3;
  120.             bitsOffset=bits&7;
  121.         }else pixelPtr+=(x-oldX)<<(logPixelSize-3);
  122.         if(y!=oldY)pixelPtr+=(long)(y-oldY)*rowBytes;
  123.     }
  124.     if(can32)SwapMMUMode((void *)&mode32);
  125.     switch(logPixelSize){
  126.         register unsigned char val;
  127.     case 0:
  128.         shift=8-1-bitsOffset;    // from right, instead of from left
  129.         mask=1<<shift;
  130.         val=((unsigned char)value<<shift)&mask;
  131.         mask=~mask;
  132.         *pixelPtr= *pixelPtr & mask | (unsigned char)val;
  133.         break;
  134.     case 1:
  135.         shift=8-2-bitsOffset;    // from right, instead of from left
  136.         mask=3<<shift;
  137.         val=((unsigned char)value<<shift)&mask;
  138.         mask=~mask;
  139.         *pixelPtr= *pixelPtr & mask | (unsigned char)val;
  140.         break;
  141.     case 2:
  142.         shift=8-4-bitsOffset;    // from right, instead of from left
  143.         mask=15<<shift;
  144.         val=((unsigned char)value<<shift)&mask;
  145.         mask=~mask;
  146.         *pixelPtr= *pixelPtr & mask | (unsigned char)val;
  147.         break;
  148.     case 3:
  149.         *pixelPtr=value;
  150.         break;
  151.     case 4:
  152.         *(unsigned short *)pixelPtr=value;
  153.         break;
  154.     case 5:
  155.         *(unsigned long *)pixelPtr=value;
  156.         break;
  157.     }
  158.     if(can32)SwapMMUMode((void *)&mode32);
  159.     oldX=x;
  160.     oldY=y;
  161. }
  162.  
  163. unsigned long GetPixmapPixel(register PixMapPtr pmPtr,int x,int y)
  164. // Returns the contents of a pixel of any size. Accepts either pixmap or bitmap.
  165. // Assumes (x,y) is in the coordinate system of the bit/pixmap.
  166. // Speed is enhanced by reusing the cached information from last time if it's the
  167. // same Pix/Bitmap as last time, i.e. same address, baseAddr,rowBytes, and bounds.
  168. // You can force it to flush its cache by passing a NULL PixMap address.
  169. {
  170.     static PixMapPtr oldPmPtr=(PixMapPtr)-1;
  171.     static int oldX,oldY;
  172.     static short rowBytes,logPixelSize,bitsOffset;
  173.     static unsigned char *pixelPtr;
  174.     static BitMap oldMap;
  175.     int shift;
  176.     signed char mode32=true32b;
  177.     Rect r;
  178.     unsigned long value;
  179.     Boolean can32;
  180.  
  181.     can32=TrapAvailable(_SwapMMUMode);
  182.     if(!USE_CACHE || pmPtr!=oldPmPtr
  183.         || pmPtr->baseAddr!=oldMap.baseAddr 
  184.         || pmPtr->rowBytes!=oldMap.rowBytes 
  185.         || *(long *)&pmPtr->bounds.top!=*(long *)&oldMap.bounds.top
  186.         || *(long *)&pmPtr->bounds.bottom!=*(long *)&oldMap.bounds.bottom){
  187.         // Cache is stale. Get fresh values.
  188.         short pixelSize;
  189.         
  190.         SetRect(&r,x,y,x+1,y+1);
  191.         pixelPtr=RectToAddress(pmPtr,&r,&rowBytes,&pixelSize,&bitsOffset);
  192.         if(pixelPtr==NULL){
  193.             oldPmPtr=(PixMapPtr)-1;    // invalidate cache
  194.             return 0;
  195.         }
  196.         oldPmPtr=pmPtr;
  197.         oldMap=*(BitMap *)pmPtr;
  198.         logPixelSize=Log2L(pixelSize);
  199.     }else{
  200.         // Is already in cache. Merely correct for changes in x and y.
  201.         if(pixelPtr==NULL)return 0;
  202.         if(logPixelSize<3){
  203.             register long bits;
  204.             bits=bitsOffset+(long)(x-oldX)<<logPixelSize;
  205.             pixelPtr+=bits>>3;
  206.             bitsOffset=bits&7;
  207.         }else pixelPtr+=(x-oldX)<<(logPixelSize-3);
  208.         if(y!=oldY)pixelPtr+=(long)(y-oldY)*rowBytes;
  209.     }
  210.     if(can32)SwapMMUMode((void *)&mode32);
  211.     switch(logPixelSize){
  212.     case 0:
  213.         shift=8-1-bitsOffset;    // from right, instead of from left
  214.         value=*pixelPtr>>shift & 1;
  215.         break;
  216.     case 1:
  217.         shift=8-2-bitsOffset;    // from right, instead of from left
  218.         value=*pixelPtr>>shift & 3;
  219.         break;
  220.     case 2:
  221.         shift=8-4-bitsOffset;    // from right, instead of from left
  222.         value=*pixelPtr>>shift & 15;
  223.         break;
  224.     case 3:
  225.         value=*pixelPtr;
  226.         break;
  227.     case 4:
  228.         value=*(unsigned short *)pixelPtr;
  229.         break;
  230.     case 5:
  231.         value=*(unsigned long *)pixelPtr;
  232.         break;
  233.     }
  234.     if(can32)SwapMMUMode((void *)&mode32);
  235.     oldX=x;
  236.     oldY=y;
  237.     return value;
  238. }
  239.  
  240. void SetDevicePixel(GDHandle device,int x,int y,unsigned long value)
  241. // Assumes (x,y) is relative to the upper left hand corner of the screen.
  242. {
  243.     if(device==NULL)return;
  244.     x+=(*(*device)->gdPMap)->bounds.left;
  245.     y+=(*(*device)->gdPMap)->bounds.top;
  246.     SetPixmapPixel(*(*device)->gdPMap,x,y,value);
  247. }
  248.  
  249. unsigned long GetDevicePixel(GDHandle device,int x,int y)
  250. // Assumes (x,y) is relative to the upper left hand corner of the screen.
  251. {
  252.     if(device==NULL)return 0;
  253.     x+=(*(*device)->gdPMap)->bounds.left;
  254.     y+=(*(*device)->gdPMap)->bounds.top;
  255.     return GetPixmapPixel(*(*device)->gdPMap,x,y);
  256. }
  257.  
  258. /*
  259. // Slightly faster than RectToAddress, but much less general. 
  260. // Requires 8-bit pixelSize. It will give wrong answer when
  261. // the pixmap is derived from a window in a multi-screen environment.
  262. unsigned char *GetPixmapPixelAddress(PixMapPtr pmPtr,int x,int y)
  263. {
  264.     register unsigned char *pixelPtr;
  265.     
  266.     if(!(pmPtr->rowBytes & 0x8000) || pmPtr->pixelSize != 8) {
  267.         PrintfExit("GetPixmapPixelAddress(): sorry, I require 8 bits/pixel.\007\n");
  268.     }
  269.     if(x<pmPtr->bounds.left || x>=pmPtr->bounds.right
  270.         || y<pmPtr->bounds.top || y>=pmPtr->bounds.bottom)return NULL;
  271.     x-=pmPtr->bounds.left;
  272.     y-=pmPtr->bounds.top;
  273.     pixelPtr=(unsigned char *)pmPtr->baseAddr;
  274.     pixelPtr+=y*(long)(pmPtr->rowBytes & 0x1fff);
  275.     pixelPtr+=x;
  276.     return pixelPtr;
  277. }
  278. */
  279.